﻿using Library.Common.Model;
using Library.Core.Application.IInfrastructure;
using Library.Core.Domain;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

namespace Library.Core.Application.BaseAction
{
    /// <summary>
    /// 1个用例对应1个类文件时使用
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class BaseEventHandler<T> where T : class
    {
        private readonly ILogger<BaseEventHandler<T>> logger;
        private readonly ICustomModelValidator modelValidator;
        public BaseEventHandler(IIocContainer container)
        {
            logger = container.Resolve<ILogger<BaseEventHandler<T>>>();
            modelValidator = container.Resolve<ICustomModelValidator>();
        }

        public abstract Task Handle(T input);

        public BaseApiResult<Tout> Handle<Tout>(Func<Tout> func, Func<Exception, Task> catchfunc = null)
        {
            var result = new BaseApiResult<Tout>();
            try
            {
                result.Data = func();
            }
            catch (Exception e)
            {
                ExHandler(result, e);
                try
                {
                    catchfunc?.Invoke(e);
                }
                catch (Exception) { }
            }
            return result;
        }

        public BaseApiResult<Tout> Handle<Tout>(T input, Func<Tout> func, Func<Exception, Task> catchfunc = null)
        {
            var result = new BaseApiResult<Tout>();
            try
            {
                ValidParm(input);
                result.Data = func();
            }
            catch (Exception e)
            {
                ExHandler(result, e);
                try
                {
                    catchfunc?.Invoke(e);
                }
                catch (Exception) { }
            }
            return result;
        }

        public async Task<BaseApiResult<Tout>> HandleAsync<Tout>(Func<Task<Tout>> func, Func<Exception, Task> catchfunc = null)
        {
            var result = new BaseApiResult<Tout>();
            try
            {
                result.Data = await func();
            }
            catch (Exception e)
            {
                ExHandler(result, e);
                try
                {
                    catchfunc?.Invoke(e);
                }
                catch (Exception) { }
            }
            return result;
        }

        public async Task<BaseApiResult<Tout>> HandleAsync<Tout>(T input, Func<Task<Tout>> func, Func<Exception, Task> catchfunc = null)
        {
            var result = new BaseApiResult<Tout>();
            try
            {
                ValidParm(input);
                result.Data = await func();
            }
            catch (Exception e)
            {
                ExHandler(result, e);
                try
                {
                    catchfunc?.Invoke(e);
                }
                catch (Exception) { }
            }
            return result;
        }

        private void ExHandler<Tout>(BaseApiResult<Tout> result, Exception e)
        {
            if (e is CustomerException)
            {
                result.Code = ((CustomerException)e).Code;
                result.ErrMessage = e.Message;
                result.Msg = e.Message;
            }
            else if (e is DbUpdateConcurrencyException)
            {
                result.Code = (int)CustomError.InvalidOperation;
                result.ErrMessage = "该数据已被别人修改,请重试！";
            }
            else
            {
                logger.LogError(e, e.Message);
                result.Code = (int)CustomError.InvalidOperation;
                result.ErrMessage = "出错了,请稍后再试";
            }
        }

        void ValidParm(T input)
        {
            var validResults = modelValidator.Valid(input);
            if (validResults.Count > 0)
            {
                throw new ApplicationsException(validResults[0].ErrorMessage);
            }
        }

    }

    /// <summary>
    /// 聚合的用例合并在一个文件时使用
    /// </summary>
    public abstract class BaseEventHandler
    {
        private readonly ILogger<BaseEventHandler> logger;
        private readonly ICustomModelValidator modelValidator;
        public BaseEventHandler(IIocContainer container)
        {
            logger = container.Resolve<ILogger<BaseEventHandler>>();
            modelValidator = container.Resolve<ICustomModelValidator>();
        }

        public abstract Task Handle<T>(T input);

        public BaseApiResult<Tout> Handle<Tout>(Func<Tout> func, Func<Exception, Task> catchfunc = null)
        {
            var result = new BaseApiResult<Tout>();
            try
            {
                result.Data = func();
            }
            catch (Exception e)
            {
                ExHandler(result, e);
                try
                {
                    catchfunc?.Invoke(e);
                }
                catch (Exception) { }
            }
            return result;
        }

        private void ExHandler<Tout>(BaseApiResult<Tout> result, Exception e)
        {
            if (e is CustomerException)
            {
                result.Code = ((CustomerException)e).Code;
                result.ErrMessage = e.Message;
            }
            else if (e is DbUpdateConcurrencyException)
            {
                result.Code = (int)CustomError.InvalidOperation;
                result.ErrMessage = "该数据已被别人修改,请重试！";
            }
            else
            {
                logger.LogError(e, e.Message);
                result.Code = (int)CustomError.InvalidOperation;
                result.ErrMessage = "出错了,请稍后再试";
            }
        }

        public BaseApiResult<Tout> Handle<Tout, T>(T input, Func<Tout> func, Func<Exception, Task> catchfunc = null)
        {
            var result = new BaseApiResult<Tout>();
            try
            {
                ValidParm(input);
                result.Data = func();
            }
            catch (Exception e)
            {
                ExHandler(result, e);
                try
                {
                    catchfunc?.Invoke(e);
                }
                catch (Exception) { }
            }
            return result;
        }

        public async Task<BaseApiResult<Tout>> HandleAsync<Tout>(Func<Task<Tout>> func, Func<Exception, Task> catchfunc = null)
        {
            var result = new BaseApiResult<Tout>();
            try
            {
                result.Data = await func();
            }
            catch (Exception e)
            {
                ExHandler(result, e);
                try
                {
                    catchfunc?.Invoke(e);
                }
                catch (Exception) { }
            }
            return result;
        }


        public async Task<BaseApiResult<Tout>> HandleAsync<Tout, T>(T input, Func<Task<Tout>> func, Func<Exception, Task> catchfunc = null)
        {
            var result = new BaseApiResult<Tout>();
            try
            {
                ValidParm(input);
                result.Data = await func();
            }
            catch (Exception e)
            {
                ExHandler(result, e);
                try
                {
                    catchfunc?.Invoke(e);
                }
                catch (Exception) { }
            }
            return result;
        }


        void ValidParm<T>(T input)
        {
            var validResults = modelValidator.Valid(input);
            if (validResults.Count > 0)
            {
                throw new ApplicationsException(validResults[0].ErrorMessage);
            }
        }
    }
}
